package mysql

import (
	"go.uber.org/zap"
	"struggle/model"
)

func CreateQuestion(question *model.Question) (err error) {
	// 涉及处理多表，需要使用事务
	tx, err := db.Begin()
	if err != nil {
		zap.L().Error("mysql transaction failed", zap.Error(err))
		return
	}
	defer ClearTransaction(tx) // 如果出现异常情况,导致没有 commit和rollback,可以用来收尾
	// 1. 新增问题表
	sqlStr := `INSERT INTO st_question (question_id, caption, content, author_id, category_id) values (?, ?, ?, ?, ?)`
	_, err = tx.Exec(sqlStr, question.QuestionID, question.Caption, question.Content, question.AuthorID, question.CategoryID)
	if err != nil {
		zap.L().Error("crate question failed", zap.Any("question", question), zap.Error(err))
		return
	}
	// 2. 新增问题扩展表
	questionEx := &model.QuestionEx{
		QuestionSn: question.QuestionID,
	}
	sqlStrEx := `INSERT INTO st_question_ex (question_sn) VALUES (?)`
	_, err = tx.Exec(sqlStrEx, questionEx.QuestionSn)
	if err != nil {
		zap.L().Error("crate question_ex failed", zap.Any("question", question), zap.Error(err))
		return
	}
	// 事务提交
	if err := tx.Commit(); err != nil {
		zap.L().Error("commit article failed", zap.Any("question", question), zap.Error(err))
	}
	return
}

func GetQuestionList(offset, limit int) (questionInfoList []*model.QuestionInfo, err error) {
	sqlStr := `SELECT *
		FROM st_question JOIN st_question_ex ON st_question.question_id = st_question_ex.question_sn
		WHERE status = 1 ORDER BY id DESC LIMIT ?, ?`
	err = db.Select(&questionInfoList, sqlStr, offset, limit)
	if err != nil {
		zap.L().Error("get question list failed", zap.Error(err))
		return
	}
	return
}

func GetQuestionCount() (answerCount int, err error) {
	sqlStr := `SELECT count(question_id) from st_question`
	err = db.Get(&answerCount, sqlStr)
	if err != nil {
		zap.L().Error("GetQuestionCount failed", zap.Error(err))
		return
	}
	return
}

func GetUserQuestionCount(sn uint64) (answerCount int, err error) {
	sqlStr := `SELECT count(question_id) FROM st_question WHERE author_id = ?`
	err = db.Get(&answerCount, sqlStr, sn)
	if err != nil {
		zap.L().Error("GetQuestionCount failed", zap.Error(err))
		return
	}
	return
}

func CheckQuestionIDExist(questionID uint64) bool {
	sqlStr := `SELECT count(id) from st_question where question_id = ?`
	count := 0
	db.Get(&count, sqlStr, questionID)
	return count > 0
}

func GetQuestion(questionID uint64) (question *model.Question, err error) {
	question = &model.Question{}
	sqlStr := `SELECT caption, content, author_id, category_id, create_time, update_time from st_question where question_id = ?`
	err = db.Get(question, sqlStr, questionID)
	if err != nil {
		zap.L().Error("get question failed", zap.Error(err))
		return
	}
	return
}

type questionDAO struct{}

var DefaultQuestion = questionDAO{}

// UpdateExView 增加问题扩展表的浏览数字段
func (q questionDAO) UpdateExView(sn uint64, count int) (err error) {
	sqlStr := `UPDATE st_question_ex SET view_num = ? WHERE question_sn = ?`
	_, err = db.Exec(sqlStr, count, sn)
	if err != nil {
		zap.L().Error("update question_ex view num failed", zap.Error(err))
		return
	}
	return
}

// 获取指定问题的扩展数据
func (q questionDAO) FindEx(sn uint64) (questionEx *model.QuestionEx, err error) {
	questionEx = &model.QuestionEx{}
	sqlStr := `SELECT question_sn, view_num, cmt_num, zan_num, updated_at FROM st_question_ex WHERE question_sn=?`
	err = db.Get(questionEx, sqlStr, sn)
	if err != nil {
		zap.L().Error("Find Question Ex failed", zap.Error(err))
		return
	}
	return
}

// UpdateExZan 更新问题扩展表字段 称赞的数量
func (q questionDAO) UpdateExZan(sn uint64, count int) error {
	sqlStr := `UPDATE st_question_ex SET zan_num = ? WHERE question_sn = ?`
	_, err := db.Exec(sqlStr, count, sn)
	if err != nil {
		zap.L().Error("update question_ex zan num failed", zap.Error(err))
		return err
	}
	return err
}

// 根据问题编号返回作者编号
func (q questionDAO) GetAuthor(sn uint64) (author uint64, err error) {
	sqlStr := `SELECT author_id FROM st_question WHERE question_id = ? LIMIT 1`
	err = db.Get(&author, sqlStr, sn)
	if err != nil {
		zap.L().Error("according question sn find user sn failed", zap.Error(err))
		return
	}
	return
}

// GetAuthorZan 返回该用户所有问题赞的总数
func (q questionDAO) GetAuthorZan(sn uint64) (count int, err error) {
	sqlStr := `SELECT sum(ex.zan_num) FROM	st_question as a, st_question_ex as ex WHERE a.question_id = ex.question_sn AND	a.author_id=?`
	err = db.Get(&count, sqlStr, sn)
	if err != nil {
		zap.L().Error("according user sn find zan sn failed", zap.Error(err))
		return
	}
	return
}
